#pragma once

#include"Requestor.hpp"



namespace xu
{
    namespace client
    {
        class RpcCaller
        {
        public:
            using Ptr = std::shared_ptr<RpcCaller>;
            using Callback = std::function<void(const Json::Value &)>;
            using Async = std::future<Json::Value>;

            RpcCaller(const Requestor::Ptr& rpc_req):_rpc_req(rpc_req)
            {}

            bool Call(const xu::BaseConnection::Ptr &conn,const std::string &method, const Json::Value &params, Json::Value &result)
            {
                //1.组织请求
                auto req_msg = MessageFactory::create<RpcRequest>();
                req_msg->SetId(UUID::uuid());
                req_msg->SetMType(MType::REQ_RPC);
                req_msg->SetMethod(method);
                req_msg->SetParams(params);

                //2.发送请求
                BaseMessage::Ptr rsp_msg;
                bool ret = _rpc_req->Send(conn,std::dynamic_pointer_cast<BaseMessage>(req_msg),rsp_msg);
                if(ret == false)
                {
                    LOG(LogLevel::ERROR)<<"同步发送失败";
                    return false;
                }

                //3.获取响应
                auto msg = std::dynamic_pointer_cast<RpcResponse>(rsp_msg);

                if(msg->Rcode() !=RCode::RCODE_OK)
                {
                    LOG(LogLevel::ERROR)<<"结果出错，具体出错原因："<<errReason(msg->Rcode());
                }

                result = msg->Result();
                LOG(LogLevel::DEBUG)<<"设置同步结果成功";

                return true;
            }

            bool Call(const xu::BaseConnection::Ptr &conn,const std::string &method, const Json::Value &params, Async &result)
            {
                //1.组织请求
                auto req_msg = MessageFactory::create<RpcRequest>();
                req_msg->SetId(UUID::uuid());
                req_msg->SetMType(MType::REQ_RPC);
                req_msg->SetMethod(method);
                req_msg->SetParams(params);

                //2.发送请求
                auto p =  std::make_shared<std::promise<Json::Value>>();

                //获取future
                result = p->get_future();
                auto cb = std::bind(&RpcCaller::Callback_1,this,p,std::placeholders::_1);
                bool ret = _rpc_req->Send(conn,std::dynamic_pointer_cast<BaseMessage>(req_msg),cb);
                if(ret == false)
                {
                    LOG(LogLevel::ERROR)<<"异步发送失败";
                    return false;
                }

                return true;

            }

            bool Call(const xu::BaseConnection::Ptr &conn,const std::string &method, const Json::Value &params, const  Callback& cb)
            {
                //1.组织请求
                auto req_msg = MessageFactory::create<RpcRequest>();
                req_msg->SetId(UUID::uuid());
                req_msg->SetMType(MType::REQ_RPC);
                req_msg->SetMethod(method);
                req_msg->SetParams(params);

                //2.发送请求 /std::function<void(const xu::BaseMessage::Ptr &)>;
                Requestor::Callback cb_call = std::bind(&RpcCaller::Callback_2,this,cb,std::placeholders::_1);
                bool ret = _rpc_req->Send(conn,std::dynamic_pointer_cast<BaseMessage>(req_msg),cb_call);
                if(ret == false)
                {
                    LOG(LogLevel::ERROR)<<"回调发送失败";
                    return false;
                }

                return true;
            }

        private:
            void Callback_2(const Callback& cb,const xu::BaseMessage::Ptr & msg)
            {
                auto rsp_msg = std::dynamic_pointer_cast<RpcResponse>(msg);
                if(rsp_msg->Rcode() !=RCode::RCODE_OK)
                {
                    LOG(LogLevel::ERROR)<<"结果出错，具体出错原因："<<errReason(rsp_msg->Rcode());
                }

                cb(rsp_msg->Result());
                LOG(LogLevel::DEBUG)<<"设置回调结果成功";
            }
            void Callback_1(std::shared_ptr<std::promise<Json::Value>> res,const BaseMessage::Ptr& msg)
            {
                auto rsp_msg = std::dynamic_pointer_cast<RpcResponse>(msg);
                if(rsp_msg->Rcode() !=RCode::RCODE_OK)
                {
                    LOG(LogLevel::ERROR)<<"结果出错，具体出错原因："<<errReason(rsp_msg->Rcode());
                }

                res->set_value(rsp_msg->Result());
                LOG(LogLevel::DEBUG)<<"设置异步结果成功";
            }

        private:
            Requestor::Ptr _rpc_req;
        };
    };
};